
#include "Matrix.h"
#include "Calculus.h"
#include "Spline.h"

#include <ctime>
#include <random>

#include <iostream>

using namespace std;
using namespace LinearAlgebra;
using namespace Calculus;
using namespace Mesh;
using namespace UniPolynomial;

const double PI = 3.1415926;

void test()
{
	HEMesh mesh;
	srand(time(0));

	// 创建 1000 个随机点
	for (int i = 0; i < 1000; i++)
	{
		float r = 1.0 * rand() / RAND_MAX + 1;
		float theta = 2 * PI * rand() / RAND_MAX;
		float phi = PI / 2 - PI * rand() / RAND_MAX;

		float x = r * cos(phi) * cos(theta);
		float y = r * cos(phi) * sin(theta);
		float z = r * sin(phi);
		mesh.CreateVertex({x, y, z});
		mesh.m_nList.push_back(vector3f(i, 0, 0));
		mesh.m_cList.push_back(rgb_space(i, 1, 0));
	}
	convexHull(&mesh);
	cout << mesh.VertexNum() << endl;
	saveMesh("test.dat", &mesh);

	cout << "Finished" << endl;
}

void test1()
{
	HEMesh mesh1;
	loadMesh("vase.dat", &mesh1);
	for (int i = 0; i < mesh1.VertexNum(); i++)
	{
		point3f &pos = mesh1.m_vList[i]->pos;
		pos.x = pos.x * 2;
		pos.y = pos.y * 2;
		pos.z = pos.z * 2;
	}
	saveMesh("vase.dat", &mesh1);
}

void test2()
{
	HEMesh mesh2;
	sphere(&mesh2, {0, 0, 0}, 1, 1, 1);
	saveMesh("sphere.dat", &mesh2);
}

void test3()
{
	HEMesh mesh3;
	cylinder(&mesh3, {0, 0, 0}, {1, 1, 1}, 0.3, 6);
	saveMesh("cylinder.dat", &mesh3);
}

void test4()
{
	quaternion p({1, 1, 1});
	quaternion q = rotate({1, 1, 1}, {1, 2, 3});
	p = q * p / q;
	p = p / p.v.x;
	cout << p.s << " " << p.v.x << " " << p.v.y << " " << p.v.z << endl;
}

void test5()
{
	BSpline spline(10, 8);
    float x = -5;
    float y = 1;
    float z = -4;

    // 控制点顺序从左到右，从后向前
    std::deque<point3f> P;
    for (int i = 0; i < 8; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            P.push_back({x, y, z});
            x += 1;
            y *= -1;
        }
        x = -5;
        z += 1;
        y *= -1;
    }

    // 设置控制点和节点向量
    spline.setCtrlPoints(P);
    spline.uniformUKnot(3, 0, 7);
    spline.uniformVKnot(3, 0, 5);

	HEMesh mesh;
	spline.toMesh(&mesh, 50, 70);
	saveMesh("spline.dat", &mesh);
}

int main()
{
	// test();
	// test1();
	// test2();
	// test3();
	// test4();
	test5();

	return 0;
}